﻿using System;
using System.Threading;

namespace TfsWrapper
{
    internal static class Shutdown
    {
        private static readonly TimeSpan SlidingTimeout = TimeSpan.FromMinutes(1);
        private static long pendingOperations;
        private static long completedOperations;
        private static DateTime timeToExit = DateTime.Now + TimeSpan.FromMinutes(1);

        static Shutdown()
        {
            new Thread(ServerShutdown)
            {
                Name = "Tfs issue tracker server shutdown thread",
                Priority = ThreadPriority.Lowest,
                IsBackground = true
            }.Start();
        }

        private static void ServerShutdown()
        {
            while (true)
            {
                try
                {
                    if (ShutdownHandle.HasExited())
                        break;

                    if (ShouldShutdownServer())
                    {
                        ShutdownHandle.LetGo();
                        break;
                    }
                    Thread.Sleep(500);
                }
                catch
                {}
            }
        }

        private static bool ShouldShutdownServer()
        {
            return Interlocked.Read(ref pendingOperations) == 0 && (timeToExit < DateTime.Now || completedOperations > 50);
        }

        public static IDisposable Auditing()
        {
            return new ServerAuditing();
        }

        private class ServerAuditing : IDisposable
        {
            public ServerAuditing()
            {
                timeToExit = DateTime.Now + SlidingTimeout;
                Interlocked.Increment(ref pendingOperations);
            }

            public void Dispose()
            {
                timeToExit = DateTime.Now + SlidingTimeout;
                Interlocked.Decrement(ref pendingOperations);
                Interlocked.Increment(ref completedOperations);
            }
        }
    }
}